package com.googlecode.kipler.satisfiability.completion.rule.individual;

import java.util.Iterator;

import com.googlecode.kipler.container.dl.ABox;
import com.googlecode.kipler.container.dl.DependencySet;
import com.googlecode.kipler.container.dl.Individual;
import com.googlecode.kipler.container.dl.WorldConstraintSystem;
import com.googlecode.kipler.satisfiability.reasoner.UnsatisfiableException;
import com.googlecode.kipler.syntax.Role;
import com.googlecode.kipler.syntax.concept.Concept;
import com.googlecode.kipler.syntax.formula.ConceptAssertion;
import com.googlecode.kipler.syntax.formula.Formula;
import com.googlecode.kipler.syntax.formula.ObjectRoleAssertion;
import com.googlecode.kipler.syntax.formula.SameIndividualAssertion;


/**
 * 
 * @author İnanç Seylan
 * 
 */
public class MergeUtility {
	private ABox aBox;

	private DependencySet dependencySet = new DependencySet();

	public MergeUtility(ABox abox) {
		this.aBox = abox;
	}

	public MergeUtility(ABox abox, DependencySet dependencySet) {
		this.aBox = abox;
		this.dependencySet = dependencySet;
	}

	/**
	 * @return the aBox
	 */
	public ABox getABox() {
		return aBox;
	}

	/**
	 * @param box
	 *            the aBox to set
	 */
	public void setABox(ABox box) {
		aBox = box;
	}

	/**
	 * @return the dependedWcs
	 */
	public DependencySet getDependencySet() {
		return dependencySet;
	}

	/**
	 * @param dependedWcs
	 *            the dependedWcs to set
	 */
	public void setDependedWcs(DependencySet dependedWcs) {
		this.dependencySet = dependedWcs;
	}

	public void mergeConcepts(String fromName, String toName)
			throws UnsatisfiableException {
		Individual from = getABox().getIndividual(fromName);
		Individual to = getABox().getIndividual(toName);
		for (Iterator<Concept> i = from.conceptIterator(); i.hasNext();) {
			Concept concept = i.next();
			ConceptAssertion ca = new ConceptAssertion(concept, to.getName());
			if (!getABox().contains(ca)) {
				manageDependency(new ConceptAssertion(concept, from.getName()),
						ca);
				getABox().add(ca);
			}
		}
	}

	public void mergeInequalities(String fromName, String toName)
			throws UnsatisfiableException {
		Individual from = getABox().getIndividual(fromName);
		Individual to = getABox().getIndividual(toName);
		for (Iterator<Individual> i = getABox().differentIndividualIterator(
				from); i.hasNext();) {
			Individual other = i.next();
			SameIndividualAssertion iaWillReplace = new SameIndividualAssertion(
					to.getName(), other.getName()).toggleNegated();
			if (!getABox().contains(iaWillReplace)) {
				SameIndividualAssertion iaToBeReplaced = new SameIndividualAssertion(
						from.getName(), other.getName()).toggleNegated();
				manageDependency(iaToBeReplaced, iaWillReplace);
				getABox().add(iaWillReplace);
			}
		}
	}

	public void mergeEdge(Role oldRole, Individual oldFrom, Individual oldTo,
			Role newRole, Individual newFrom, Individual newTo)
			throws UnsatisfiableException {
		if (!aBox.containsEdge(newRole, newFrom, newTo)) {
			ObjectRoleAssertion newFormula = new ObjectRoleAssertion(newRole,
					newFrom.getName(), newTo.getName());
			ObjectRoleAssertion oldFormula = new ObjectRoleAssertion(oldRole,
					oldFrom.getName(), oldTo.getName());
			manageDependency(oldFormula, newFormula);
			aBox.add(newFormula);
		}
	}

	private void manageDependency(Formula formulaToBeReplaced,
			Formula formulaThatWillReplace) {
		WorldConstraintSystem wcs = getABox().getWorld().getWcs();
		wcs.getData().getDependencyManager().move(formulaThatWillReplace,
				formulaToBeReplaced);
		if (getDependencySet() != null) {
			wcs.getData().getDependencyManager().addAll(formulaThatWillReplace,
					getDependencySet());
		}
	}
}
